package com.sky.aop;

import com.sky.annotation.AutoFill;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * 切面类-完成数据的自动填充
 */
@Aspect
@Component
public class AutoFillAspect {

    /**
     * 找到哪些方法需要增强
     *  com.sky.mapper包下的所有的类里面添加了AutoFill注解的方法
     */
    @Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")
    private void pointcut(){}

    @Before("pointcut()")
    public void autoFill(JoinPoint joinPoint){
//        1. 通过反射拿到方法上的注解-方法的元数据
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        //如果当前的方法上添加了AutoFill注解就返回true 如果没有就返回false
        if(method.isAnnotationPresent(AutoFill.class)){ // 健壮性的判断
            AutoFill autoFill = method.getAnnotation(AutoFill.class);
            //2. 通过注解获取注解的值
            OperationType operationType = autoFill.value();

            //3. 获取mapper方法上的参数
            Object[] args = joinPoint.getArgs();
            if(null == args || args.length == 0){
                return;
            }

            Object entity = args[0];//获取的一定是参数的第一个数据

            //4. 构建数据
            LocalDateTime now = LocalDateTime.now();
            Long currentUserId = BaseContext.getCurrentUserId();

            if(operationType.equals(OperationType.INSERT)){
                //5. 如果是insert 设置4个值
                try {
                    Method setCreateTime = entity.getClass().getDeclaredMethod("setCreateTime", LocalDateTime.class);
                    Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
                    Method setCreateUser = entity.getClass().getDeclaredMethod("setCreateUser", Long.class);
                    Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);

                    setCreateTime.invoke(entity, now);
                    setUpdateTime.invoke(entity, now);

                    setCreateUser.invoke(entity, currentUserId);
                    setUpdateUser.invoke(entity, currentUserId);


                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }


            }else{
                //6. 如果是update就设置2个值
                try {
                    Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);
                    Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);

                    setUpdateTime.invoke(entity, now);
                    setUpdateUser.invoke(entity, currentUserId);

                } catch (NoSuchMethodException e) {
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                } catch (InvocationTargetException e) {
                    e.printStackTrace();
                }

            }
        }

    }
}
